use diesel::*;

use common::pagination::{calc_page_count, Pagination, PaginationForm};
use super::establish_connection;
use model::post::{Post, PostNew, PostPage, PostUpdate};
use model::schema::posts;
use model::schema::posts::dsl::*;

pub struct PostDao;

impl PostDao {

    /// 分页查询
    pub fn page(&self, page: PostPage) -> Pagination<Post>{
        let connection = establish_connection();
        let build_query = || {
            let mut query = posts::table.into_boxed();
            if page.title.len() > 0 {
                query = query.filter(title.like(format!("%{}%", page.title.clone())));
            }
            query
        };
        let mut query = build_query();
        let total = query.count()
            .get_result(&connection)
            .unwrap_or(0);

        let mut rows = vec![];
        if total > 0 {
            query = build_query();
            rows = query
                .offset(page.get_offset())
                .limit(page.page_size)
                .load::<Post>(&connection)
                .expect("Error loading posts");
        }
        Pagination {
            total,
            page_index: page.page_index,
            page_size: page.page_size,
            page_count: calc_page_count(total, page.page_size),
            rows: rows
        }
    }

    pub fn list_posts(&self) -> Vec<Post> {
        let connection = establish_connection();
        let results = posts
            .filter(published.eq(true))
            .limit(5)
            .load::<Post>(&connection)
            .expect("Error loading posts");
        results
    }

    pub fn get_by_id(&self, id_val: i32) -> Result<Post, diesel::result::Error> {
        let connection = establish_connection();
        posts.find(id_val).first(&connection)
    }

    pub fn add(&self, post: &PostNew) {
        let connection = establish_connection();
        let insert_rows = diesel::insert_into(posts::table)
            .values(post)
            .execute(&connection)
            .expect("error insert");
        if insert_rows == 0 {
            log::error!("insert failed for {:?}", post);
        }
    }

    pub fn update(&self, post: &PostUpdate) {
        let connection = establish_connection();

        diesel::update(posts.find(post.id))
            .set((
                published.eq(post.published),
                title.eq(post.title.clone()),
                body.eq(post.body.clone())
            ))
            .execute(&connection)
            .expect(&format!("Unable to find post {}", post.id));
    }

    pub fn delete(&self, id_val: i32) {
        let connection = establish_connection();
        diesel::delete(posts.filter(id.eq(id_val)))
            .execute(&connection)
            .expect("Error deleting posts");
    }
}

